package org.springblade.modules.device.service.impl;

import com.alibaba.fastjson.JSON;
import com.aliyun.openservices.log.common.LogContent;
import com.aliyun.openservices.log.common.LogItem;
import com.aliyun.openservices.log.common.QueriedLog;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.SpringUtil;
import org.springblade.modules.aliemail.AliEmailProperties;
import org.springblade.modules.aliemail.AliEmailService;
import org.springblade.modules.alisls.AliSlsProperties;
import org.springblade.modules.alisls.AliyunSlsService;
import org.springblade.modules.device.dto.DeviceAlertDto;
import org.springblade.modules.device.dto.DeviceInfoSaveDto;
import org.springblade.modules.device.service.IDeviceInfoService;
import org.springblade.modules.device.vo.DeviceInfoVo;
import org.springblade.modules.device.vo.DeviceRunStatusVo;
import org.springblade.modules.device.vo.SalesOrderNoVo;
import org.springblade.modules.teambition.util.HttpUtil;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class DeviceInfoServiceImpl implements IDeviceInfoService {
	private final String DEVICE_TOPIC = "device";
	@Resource
	private AliyunSlsService aliyunSlsService;
	@Resource
	private AliSlsProperties aliSlsProperties;

	@Override
	public Boolean submitDeviceInfo(DeviceInfoSaveDto deviceInfoSaveDto) {
		log.info("保存设备信息{}",JSON.toJSONString(deviceInfoSaveDto));
		Map<String, Object> stringObjectMap = convertToMap(deviceInfoSaveDto);
		List<AliyunSlsService.LogContent> contents = new ArrayList<>();
		stringObjectMap.forEach((k,v)->{
			boolean empty = Func.isEmpty(v)||"null".equals(v);
			AliyunSlsService.LogContent logContent = new AliyunSlsService.LogContent(k, empty ?"":String.valueOf(v));
			contents.add(logContent);

		});
		String deviceNo = deviceInfoSaveDto.getDeviceNo();
		try {
			SpringUtil.getBean(AliyunSlsService.class).pushLog(DEVICE_TOPIC,deviceNo, contents,SpringUtil.getBean(AliSlsProperties.class).getDeviceLogstore());
		} catch (Exception e) {
			e.printStackTrace();
		}
		return true;
	}

	public static Map<String, Object> convertToMap(Object obj) {
		Map<String, Object> map = new HashMap<>();

		try {
			Class<?> clazz = obj.getClass();
			for (Field field : clazz.getDeclaredFields()) {
				field.setAccessible(true); // 允许访问私有字段
				map.put(field.getName(), field.get(obj));
			}
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}

		return map;
	}


	@Override
	public DeviceInfoVo getDeviceInfo(String deviceNo,String salesOrderNo) {
		String startTime = SpringUtil.getBean(AliSlsProperties.class).getStartTime();
		// 设置查询时间范围（最近1小时）
		Date start = DateUtil.parse(startTime, "yyyy-MM-dd");

//		int from = (int)((System.currentTimeMillis() / 1000) - 3600);
		int from = (int)(start.getTime()/1000);
		int to = (int)(System.currentTimeMillis() / 1000);
		QueriedLog device = null;
		if(StringUtils.isNotBlank(salesOrderNo)){
			device = SpringUtil.getBean(AliyunSlsService.class).getLatestLogByFields(aliSlsProperties.getDeviceLogstore(), DEVICE_TOPIC,"salesOrderNo",salesOrderNo, from, to);
		}else {
			device = SpringUtil.getBean(AliyunSlsService.class).getLatestLogByFields(aliSlsProperties.getDeviceLogstore(), DEVICE_TOPIC,"deviceNo",deviceNo, from, to);
//			device = SpringUtil.getBean(AliyunSlsService.class).getLatestLogByTopic(SpringUtil.getBean(AliSlsProperties.class).getDeviceLogstore(), DEVICE_TOPIC, from, to);
		}
		if(Func.isNotEmpty(device)){
			LogItem mLogItem = device.mLogItem;
//			return logItem2Map(mLogItem);
			DeviceInfoVo deviceInfoVo = new DeviceInfoVo();
			trans2Object(deviceInfoVo, mLogItem);
			String time___0 = mLogItem.GetLogContents().stream().filter(x -> x.getKey().equals("__time___0")).findFirst().map(LogContent::getValue).orElse("");
			Date date = new Date(Long.parseLong(time___0)*1000);
			String time = DateUtil.format(date,"yyyy-MM-dd HH:mm:ss");
			deviceInfoVo.setTime(time);
			return  deviceInfoVo;
		}
		return null;
	}


	@Override
	public List<String> getSaleOrders() {
		String startTime = SpringUtil.getBean(AliSlsProperties.class).getStartTime();
		// 设置查询时间范围（最近1小时）
		Date start = DateUtil.parse(startTime, "yyyy-MM-dd");

//		int from = (int)((System.currentTimeMillis() / 1000) - 3600);
		int from = (int)(start.getTime()/1000);
		int to = (int)(System.currentTimeMillis() / 1000);
		List<QueriedLog> queriedLogs = aliyunSlsService.getLogsByFields(aliSlsProperties.getDeviceLogstore(), DEVICE_TOPIC, from, to);
		List<SalesOrderNoVo> collect = queriedLogs.stream().map(x -> {
			SalesOrderNoVo deviceInfoVo = new SalesOrderNoVo();
			LogItem mLogItem = x.mLogItem;
			ArrayList<LogContent> logContents = mLogItem.GetLogContents();
			return (SalesOrderNoVo) trans2Object(deviceInfoVo, mLogItem);
		}).collect(Collectors.toList());
		return collect.stream().map(SalesOrderNoVo::getSalesOrderNo).distinct().collect(Collectors.toList());
	}

    @Override
    public Object alert2(String content, String toMail, String deviceNo) {
		String alarmType = "Device onlineStatus";
		String html = buildEmailBody(deviceNo, content,alarmType);
		SpringUtil.getBean(AliEmailService.class).sendEmail(toMail,"Emergency alarm",html);
        return true;
    }

	@Override
	public boolean sendAlert(DeviceAlertDto deviceAlertDto) {
		String merchantEmail = getMerchantEmail(deviceAlertDto.getMerchantId());
		if (StringUtils.isBlank(merchantEmail)) {
			log.info("merchantId未配置邮箱地址{}",deviceAlertDto.getMerchantId());
			return false;
		}
		String content = "";
		boolean exceptionFlag = false;
		String alarmType = "";
		if(DeviceAlertDto.TAG_STATUS.equals(deviceAlertDto.getDeviceAlertTag())&&deviceAlertDto.getStatus()==2){
			content = "Device offline";
			exceptionFlag = true;
			alarmType = "Device onlineStatus";
		}else if(DeviceAlertDto.TAG_RUN_STATUS.equals(deviceAlertDto.getDeviceAlertTag())&&deviceAlertDto.getDeviceRunStatus()==2){
			content = deviceAlertDto.getExceptionRemark();
			exceptionFlag = true;
			alarmType = "device exception";
		}else if(DeviceAlertDto.TAG_SCARCE_STATUS.equals(deviceAlertDto.getDeviceAlertTag())&&(deviceAlertDto.getDeviceScarceStatus()==2||deviceAlertDto.getDeviceScarceStatus() ==3)){
			content = deviceAlertDto.getScarceRemark();
			exceptionFlag = true;
			alarmType = "missing ingredients ";
		}
		log.info("告警推送{}=>{}===>{}",exceptionFlag,merchantEmail,content);
		if(exceptionFlag){
			log.info("告警推送文本{}===>{}",merchantEmail,content);
			String s = buildEmailBody(deviceAlertDto.getDeviceNo(), content, alarmType);
			SpringUtil.getBean(AliEmailService.class).sendEmail(merchantEmail,"Vending Machine Alert",s);
		}
		return exceptionFlag;
	}

	private String getMerchantEmail(String merchantId){
		try {
			String url = SpringUtil.getBean(AliEmailProperties.class).getMerchantMailUrl()+merchantId;
			RestTemplate restTemplate = new RestTemplate();
			R<String> status = R.status(true);
			ResponseEntity<? extends R> forEntity = restTemplate.getForEntity(url, status.getClass());
			R<String> body = forEntity.getBody();
			return body.getData();
		} catch (Exception e) {
			log.error("获取用户邮箱失败",e);
			return "";
		}
	}

	private String buildEmailBody(String deviceNo, String content ,String alarmType){
		return
			 "Alert Type:" + alarmType +"<br>"
			+ "Alert Content:  " +content + "<br>"
			+ "Device ID:" + deviceNo +"<br>";
	}

	private Object trans2Object(Object o, LogItem logItem){
		List<LogContent> logContents = logItem.GetLogContents();
		Class<?> aClass = o.getClass();
		Field[] declaredFields = aClass.getDeclaredFields();
		for (Field declaredField : declaredFields) {
			String name = declaredField.getName();
			String byField = getByField(name.toLowerCase(), logContents);
			// 设置访问权限为true，以便可以访问私有字段
			declaredField.setAccessible(true);
			// 设置字段值
			try {
				declaredField.set(o, byField);
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
		}
		return o;
	}

	private String getByField(String field,List<LogContent> logContents){
		for (LogContent logContent : logContents) {
			String key = logContent.getKey();
			String value = logContent.getValue();
			int a = 5;
			int z = 6;
		}
		return logContents.stream().filter(x -> x.getKey().equals(field)).findFirst().map(LogContent::getValue).orElse("");
	}

		private Map<String, Object> logItem2Map(LogItem logItem){
		List<LogContent> logContents = logItem.GetLogContents();
		Map<String, Object> data = new HashMap<>();
		for (LogContent logContent : logContents) {
			String key = logContent.getKey();
			String value = logContent.getValue();
			data.put(key,value);
		}
		return data;
	}

}
